package com.zx.zxpicture.infrstructure.utils;

import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.script.DefaultRedisScript;

import java.util.Collections;
import java.util.concurrent.TimeUnit;

/**
 * redis分布式锁工具类
 */
public class RedisLockUtil {

    //脚本
    private static final DefaultRedisScript<Long> UNLOCK_SCRIPT;
    //静态代码块
    //初始化脚本
    static {
        UNLOCK_SCRIPT = new DefaultRedisScript<>();//创建对象
        UNLOCK_SCRIPT.setLocation(new ClassPathResource("unlock.lua"));//指定脚本位置
        UNLOCK_SCRIPT.setResultType(Long.class);
    }
    /**
     * 获取分布式锁
     * @param stringRedisTemplate 操作redis客户端
     * @param lockKey 锁的key
     * @param value 锁的标识(线程id)
     * @return
     */
    public static Boolean redisTryLock(StringRedisTemplate stringRedisTemplate,String lockKey,String value,long timeout,TimeUnit timeUnit){
        ValueOperations<String, String> stringValueOperations = stringRedisTemplate.opsForValue();
        //这个操作是具有原子性的，(先检查再插入)不会被其他线程插入
        return stringValueOperations.setIfAbsent(lockKey, value, timeout, timeUnit);
    }

    /**
     * 调用lua脚本释放锁 0-成功 1-失败
     * @param stringRedisTemplate 操作redis客户端
     * @param lockKey 锁的key
     * @param lockValue 锁的标识(线程id)
     * @return
     */
    public static Long unLock(StringRedisTemplate stringRedisTemplate,String lockKey,String lockValue) {
        //调用lua脚本
        return stringRedisTemplate.execute(
                UNLOCK_SCRIPT,
                Collections.singletonList(lockKey),
                lockValue
        );
    }
}
